home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcl / pcl-rev4.lha / fin.lisp < prev    next >
Text File  |  1990-11-26  |  66KB  |  1,890 lines

  1. ;;;-*-Mode:LISP; Package:(PCL Lisp 1000); Base:10; Syntax:Common-lisp -*-
  2. ;;;
  3. ;;; *************************************************************************
  4. ;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
  5. ;;; All rights reserved.
  6. ;;;
  7. ;;; Use and copying of this software and preparation of derivative works
  8. ;;; based upon this software are permitted.  Any distribution of this
  9. ;;; software or derivative works must comply with all applicable United
  10. ;;; States export control laws.
  11. ;;; 
  12. ;;; This software is made available AS IS, and Xerox Corporation makes no
  13. ;;; warranty about the software, its performance or its conformity to any
  14. ;;; specification.
  15. ;;; 
  16. ;;; Any person obtaining a copy of this software is requested to send their
  17. ;;; name and post office or electronic mail address to:
  18. ;;;   CommonLoops Coordinator
  19. ;;;   Xerox PARC
  20. ;;;   3333 Coyote Hill Rd.
  21. ;;;   Palo Alto, CA 94304
  22. ;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
  23. ;;;
  24. ;;; Suggestions, comments and requests for improvements are also welcome.
  25. ;;; *************************************************************************
  26. ;;;
  27.  
  28.   ;;   
  29. ;;;;;; FUNCALLABLE INSTANCES
  30.   ;;
  31.  
  32. #|
  33.  
  34. Generic functions are instances with meta class funcallable-standard-class.
  35. Instances with this meta class are called funcallable-instances (FINs for
  36. short).  They behave something like lexical closures in that they have data
  37. associated with them (which is used to store the slots) and are funcallable.
  38. When a funcallable instance is funcalled, the function that is invoked is
  39. called the funcallable-instance-function.  The funcallable-instance-function
  40. of a funcallable instance can be changed.
  41.  
  42. This file implements low level code for manipulating funcallable instances.
  43.  
  44. It is possible to implement funcallable instances in pure Common Lisp.  A
  45. simple implementation which uses lexical closures as the instances and a
  46. hash table to record that the lexical closures are funcallable instances
  47. is easy to write.  Unfortunately, this implementation adds significant
  48. overhead:
  49.  
  50.    to generic-function-invocation (1 function call)
  51.    to slot-access (1 function call or one hash table lookup)
  52.    to class-of a generic-function (1 hash-table lookup)
  53.  
  54. In addition, it would prevent the funcallable instances from being garbage
  55. collected.  In short, the pure Common Lisp implementation really isn't
  56. practical.
  57.  
  58. Instead, PCL uses a specially tailored implementation for each Common Lisp and
  59. makes no attempt to provide a purely portable implementation.  The specially
  60. tailored implementations are based on the lexical closure's provided by that
  61. implementation and are fairly short and easy to write.
  62.  
  63. Some of the implementation dependent code in this file was originally written
  64. by someone in the employ of the vendor of that Common Lisp.  That code is
  65. explicitly marked saying who wrote it.
  66.  
  67. |#
  68.  
  69. (in-package 'pcl)
  70.  
  71. ;;;
  72. ;;; The first part of the file contains the implementation dependent code to
  73. ;;; implement funcallable instances.  Each implementation must provide the
  74. ;;; following functions and macros:
  75. ;;; 
  76. ;;;    ALLOCATE-FUNCALLABLE-INSTANCE-1 ()
  77. ;;;       should create and return a new funcallable instance.  The
  78. ;;;       funcallable-instance-data slots must be initialized to NIL.
  79. ;;;       This is called by allocate-funcallable-instance and by the
  80. ;;;       bootstrapping code.
  81. ;;;
  82. ;;;    FUNCALLABLE-INSTANCE-P (x)
  83. ;;;       the obvious predicate.  This should be an INLINE function.
  84. ;;;       it must be funcallable, but it would be nice if it compiled
  85. ;;;       open.
  86. ;;;
  87. ;;;    SET-FUNCALLABLE-INSTANCE-FUNCTION (fin new-value)
  88. ;;;       change the fin so that when it is funcalled, the new-value
  89. ;;;       function is called.  Note that it is legal for new-value
  90. ;;;       to be copied before it is installed in the fin, specifically
  91. ;;;       there is no accessor for a FIN's function so this function
  92. ;;;       does not have to preserve the actual new value.  The new-value
  93. ;;;       argument can be any funcallable thing, a closure, lambda
  94. ;;;       compiled code etc.  This function must coerce those values
  95. ;;;       if necessary.
  96. ;;;       NOTE: new-value is almost always a compiled closure.  This
  97. ;;;             is the important case to optimize.
  98. ;;;
  99. ;;;    FUNCALLABLE-INSTANCE-DATA-1 (fin data-name)
  100. ;;;       should return the value of the data named data-name in the fin.
  101. ;;;       data-name is one of the symbols in the list which is the value
  102. ;;;       of funcallable-instance-data.  Since data-name is almost always
  103. ;;;       a quoted symbol and funcallable-instance-data is a constant, it
  104. ;;;       is possible (and worthwhile) to optimize the computation of
  105. ;;;       data-name's offset in the data part of the fin.
  106. ;;;       This must be SETF'able.
  107. ;;;       
  108.  
  109. (defconstant funcallable-instance-data
  110.              '(wrapper slots)
  111.   "These are the 'data-slots' which funcallable instances have so that
  112.    the meta-class funcallable-standard-class can store class, and static
  113.    slots in them.")
  114.  
  115. (defmacro funcallable-instance-data-position (data)
  116.   (if (and (consp data)
  117.            (eq (car data) 'quote)
  118.            (boundp 'funcallable-instance-data))
  119.       (or (position (cadr data) funcallable-instance-data :test #'eq)
  120.           (progn
  121.             (warn "Unknown funcallable-instance data: ~S." (cadr data))
  122.             `(error "Unknown funcallable-instance data: ~S." ',(cadr data))))
  123.       `(position ,data funcallable-instance-data :test #'eq)))
  124.  
  125. (defun called-fin-without-function ()
  126.   (error "Attempt to funcall a funcallable-instance without first~%~
  127.           setting its funcallable-instance-function."))
  128.  
  129.  
  130.  
  131.  
  132. ;;;
  133. ;;; In Lucid Lisp, compiled functions and compiled closures have the same
  134. ;;; representation.  They are called procedures.  A procedure is a basically
  135. ;;; just a constants vector, with one slot which points to the CODE.  This
  136. ;;; means that constants and closure variables are intermixed in the procedure
  137. ;;; vector.
  138. ;;;
  139. ;;; This code was largely written by JonL@Lucid.com.  Problems with it should
  140. ;;; be referred to him.
  141. ;;; 
  142. #+Lucid
  143. (progn
  144.  
  145. (defconstant procedure-is-funcallable-instance-bit-position 10)
  146.  
  147. (defconstant fin-trampoline-fun-index lucid::procedure-literals)
  148.  
  149. (defconstant fin-size (+ fin-trampoline-fun-index
  150.              (length funcallable-instance-data)
  151.              1))
  152.  
  153. ;;;
  154. ;;; The inner closure of this function will have its code vector replaced
  155. ;;;  by a hand-coded fast jump to the function that is stored in the 
  156. ;;;  captured-lexical variable.  In effect, that code is a hand-
  157. ;;;  optimized version of the code for this inner closure function.
  158. ;;;
  159. (defun make-trampoline (function)
  160.   (declare (optimize (speed 3) (safety 0)))
  161.   #'(lambda (&rest args)
  162.       (apply function args)))
  163.  
  164. (eval-when (eval) 
  165.   (compile 'make-trampoline)
  166.   )
  167.  
  168.  
  169. (defun binary-assemble (codes)
  170.   (let* ((ncodes (length codes))
  171.      (code-vec #-LCL3.0 (lucid::new-code ncodes)
  172.            #+LCL3.0 (lucid::with-current-area 
  173.                 lucid::*READONLY-NON-POINTER-AREA*
  174.                   (lucid::new-code ncodes))))
  175.     (declare (fixnum ncodes))
  176.     (do ((l codes (cdr l))
  177.      (i 0 (1+ i)))
  178.     ((null l) nil)
  179.       (declare (fixnum i))
  180.       (setf (lucid::code-ref code-vec i) (car l)))
  181.     code-vec))
  182.  
  183. ;;;
  184. ;;; Egad! Binary patching!
  185. ;;; See comment following definition of MAKE-TRAMPOLINE -- this is just
  186. ;;;  the "hand-optimized" machine instructions to make it work.
  187. ;;;
  188. (defvar *mattress-pad-code* 
  189.     (binary-assemble
  190.         #+MC68000
  191.         '(#x2A6D #x11 #x246D #x1 #x4EEA #x5)
  192.         #+SPARC
  193.         (ecase (lucid::procedure-length #'lucid::false)
  194.           (5
  195.            '(#xFA07 #x6012 #xDE07 #x7FFE #x81C3 #xFFFE #x100 #x0))
  196.           (8
  197.            `(#xFA07 #x601E #xDE07 #x7FFE #x81C3 #xFFFE #x100 #x0)))
  198.         #+(and BSP (not LCL3.0 ))
  199.         '(#xCD33 #x11 #xCDA3 #x1 #xC19A #x5 #xE889)
  200.         #+(and BSP LCL3.0)
  201.         '(#x7733 #x7153 #xC155 #x5 #xE885)
  202.         #+I386
  203.         '(#x87 #xD2 #x8B #x76 #xE #xFF #x66 #xFE)
  204.         #+VAX
  205.         '(#xD0 #xAC #x11 #x5C #xD0 #xAC #x1 #x57 #x17 #xA7 #x5)
  206.         #+PA
  207.         '(#x4891 #x3C #xE461 #x6530 #x48BF #x3FF9)
  208.         #-(or MC68000 SPARC BSP I386 VAX PA)
  209.         '(0 0 0 0)))
  210.  
  211.  
  212. (lucid::defsubst funcallable-instance-p (x)
  213.   (and (lucid::procedurep x)
  214.        (lucid::logbitp& procedure-is-funcallable-instance-bit-position
  215.                         (lucid::procedure-ref x lucid::procedure-flags))))
  216.  
  217. (lucid::defsubst set-funcallable-instance-p (x)
  218.   (if (not (lucid::procedurep x))
  219.       (error "Can't make a non-procedure a fin.")
  220.       (setf (lucid::procedure-ref x lucid::procedure-flags)
  221.         (logior (expt 2 procedure-is-funcallable-instance-bit-position)
  222.             (the fixnum
  223.              (lucid::procedure-ref x lucid::procedure-flags))))))
  224.  
  225.  
  226. (defun allocate-funcallable-instance-1 ()
  227.   #+Prime
  228.   (declare (notinline lucid::new-procedure))    ;fixes a bug in Prime 1.0 in
  229.                                                 ;which new-procedure expands
  230.                                                 ;incorrectly
  231.   (let ((new-fin (lucid::new-procedure fin-size))
  232.     (fin-index fin-size))
  233.     (declare (fixnum fin-index)
  234.          (type lucid::procedure new-fin))
  235.     (dotimes (i (length funcallable-instance-data)) 
  236.       ;; Initialize the new funcallable-instance.  As part of our contract,
  237.       ;; we have to make sure the initial value of all the funcallable
  238.       ;; instance data slots is NIL.
  239.       (decf fin-index)
  240.       (setf (lucid::procedure-ref new-fin fin-index) nil))
  241.     ;;
  242.     ;; "Assemble" the initial function by installing a fast "trampoline" code;
  243.     ;; 
  244.     (setf (lucid::procedure-ref new-fin lucid::procedure-code)
  245.       *mattress-pad-code*)
  246.     ;; Disable argcount checking in the "mattress-pad" code for
  247.     ;;  ports that go through standardized trampolines
  248.     #+PA (setf (sys:procedure-ref new-fin lucid::procedure-arg-count) -1)
  249.     #+MIPS (progn
  250.          (setf (sys:procedure-ref new-fin lucid::procedure-min-args) 0)
  251.          (setf (sys:procedure-ref new-fin lucid::procedure-max-args) 
  252.            call-arguments-limit))
  253.     ;; but start out with the function to be run as an error call.
  254.     (setf (lucid::procedure-ref new-fin fin-trampoline-fun-index)
  255.       #'called-fin-without-function)
  256.     ;; Then mark it as a "fin"
  257.     (set-funcallable-instance-p new-fin)
  258.     new-fin))
  259.  
  260. (defun set-funcallable-instance-function (fin new-value)
  261.   (unless (funcallable-instance-p fin)
  262.     (error "~S is not a funcallable-instance" fin))
  263.   (if (lucid::procedurep new-value)
  264.       (progn
  265.     (setf (lucid::procedure-ref fin fin-trampoline-fun-index) new-value)
  266.     fin)
  267.       (progn 
  268.     (unless (functionp new-value)
  269.       (error "~S is not a function." new-value))
  270.     ;; 'new-value' is an interpreted function.  Install a
  271.     ;; trampoline to call the interpreted function.
  272.     (set-funcallable-instance-function fin
  273.                        (make-trampoline new-value)))))
  274.  
  275. (defmacro funcallable-instance-data-1 (instance data)
  276.   `(lucid::procedure-ref 
  277.        ,instance
  278.        (the fixnum
  279.         (- (- fin-size 1)
  280.            (the fixnum (funcallable-instance-data-position ,data))))))
  281.   
  282. );end of #+Lucid
  283.  
  284.  
  285. ;;;
  286. ;;; In Symbolics Common Lisp, a lexical closure is a pair of an environment
  287. ;;; and an ordinary compiled function.  The environment is represented as
  288. ;;; a CDR-coded list.  I know of no way to add a special bit to say that the
  289. ;;; closure is a FIN, so for now, closures are marked as FINS by storing a
  290. ;;; special marker in the last cell of the environment.
  291. ;;; 
  292. ;;;  The new structure of a fin is:
  293. ;;;     (lex-env lex-fun *marker* fin-data0 fin-data1)
  294. ;;;  The value returned by allocate is a lexical-closure pointing to the start
  295. ;;;  of the fin list.  Benefits are: no longer ever have to copy environments,
  296. ;;;  fins can be much smaller (5 words instead of 18), old environments never
  297. ;;;  get destroyed (so running dcodes dont have the lex env change from under
  298. ;;;  them any longer).
  299. ;;;
  300. ;;;  Most of the fin operations speed up a little (by as much as 30% on a
  301. ;;;  3650), at least one nasty bug is fixed, and so far at least I've not
  302. ;;;  seen any problems at all with this code.   - mike thome (mthome@bbn.com)
  303. ;;;      
  304. #+(and Genera (not Genera-Release-8))
  305. (progn
  306.  
  307. (defvar *funcallable-instance-marker* (list "Funcallable Instance Marker"))
  308.  
  309. (defun allocate-funcallable-instance-1 ()
  310.   (let* ((whole-fin (make-list (+ 3 (length funcallable-instance-data))))
  311.      (new-fin (sys:%make-pointer-offset sys:dtp-lexical-closure
  312.                         whole-fin
  313.                         0)))
  314.     ;;
  315.     ;; note that we DO NOT turn the real lex-closure part of the fin into
  316.     ;; a dotted pair, because (1) the machine doesn't care and (2) if we
  317.     ;; did the garbage collector would reclaim everything after the lexical
  318.     ;; function.
  319.     ;; 
  320.     (setf (sys:%p-contents-offset new-fin 2) *funcallable-instance-marker*)
  321.     (setf (si:lexical-closure-function new-fin)
  322.       #'(lambda (ignore &rest ignore-them-too)
  323.           (declare (ignore ignore ignore-them-too))
  324.           (called-fin-without-function)))
  325.     #+ignore
  326.     (setf (si:lexical-closure-environment new-fin) nil)
  327.     new-fin))
  328.  
  329. (scl:defsubst funcallable-instance-p (x)
  330.   (declare (inline si:lexical-closure-p))
  331.   (and (si:lexical-closure-p x)
  332.        (= (sys:%p-cdr-code (sys:%make-pointer-offset sys:dtp-compiled-function x 1))
  333.       sys:cdr-next)
  334.        (eq (sys:%p-contents-offset x 2) *funcallable-instance-marker*)))
  335.  
  336. (defun set-funcallable-instance-function (fin new-value)
  337.   (cond ((not (funcallable-instance-p fin))
  338.          (error "~S is not a funcallable-instance" fin))
  339.         ((not (or (functionp new-value)
  340.           (and (consp new-value)
  341.                (eq (car new-value) 'si:digested-lambda))))
  342.          (error "~S is not a function." new-value))
  343.         ((and (si:lexical-closure-p new-value)
  344.           (compiled-function-p (si:lexical-closure-function new-value)))
  345.      (let ((env (si:lexical-closure-environment new-value))
  346.            (fn  (si:lexical-closure-function new-value)))
  347.        ;; we only have to copy the pointers!!
  348.        (setf (si:lexical-closure-environment fin) env
  349.          (si:lexical-closure-UNnction fin)    fn)
  350. ;       (dbg:set-env->fin env fin)
  351.        ))
  352.         (t
  353.          (set-funcallable-instance-function fin
  354.                                             (make-trampoline new-value)))))
  355.  
  356. (defun make-trampoline (function)
  357.   (declare (optimize (speed 3) (safety 0)))
  358.   #'(lambda (&rest args)
  359.       #+Genera (declare (dbg:invisible-frame :pcl-internals))
  360.       (apply function args)))
  361.  
  362. (defmacro funcallable-instance-data-1 (fin data)
  363.   `(sys:%p-contents-offset ,fin
  364.                (+ 3 (funcallable-instance-data-position ,data))))
  365.  
  366. (defsetf funcallable-instance-data-1 (fin data) (new-value)
  367.   `(setf (sys:%p-contents-offset ,fin
  368.                  (+ 3 (funcallable-instance-data-position ,data)))
  369.      ,new-value))
  370.  
  371. ;;;
  372. ;;; Make funcallable instances print out properly.
  373. ;;; 
  374. (defvar *old-print-lexical-closure*)
  375.  
  376. (defvar *print-lexical-closure* nil)
  377.  
  378. (defun pcl-print-lexical-closure (exp stream slashify-p &optional (depth 0))
  379.   (declare (ignore depth))
  380.   (declare (special *boot-state*))
  381.   (if (or (eq *print-lexical-closure* exp)
  382.       (neq *boot-state* 'complete)
  383.       (eq (class-of exp) *the-class-t*))
  384.       (let ((*print-lexical-closure* nil))
  385.     (funcall *old-print-lexical-closure* exp stream slashify-p))
  386.       (let ((*print-escape* slashify-p)
  387.         (*print-lexical-closure* exp))
  388.     (print-object exp stream))))
  389.  
  390. (eval-when (load eval)
  391.   (unless (boundp '*boot-state*)
  392.     (setq *boot-state* nil))
  393.   (unless (boundp '*old-print-lexical-closure*)
  394.     (setq *old-print-lexical-closure* #'si:print-lexical-closure)
  395.     (setf (symbol-function 'si:print-lexical-closure)
  396.       'pcl-print-lexical-closure)))
  397.  
  398. (defvar *old-function-name*)
  399.  
  400. (defun new-function-name (function)
  401.   (declare (special *boot-state*))
  402.   (or (and (eq *boot-state* 'complete)
  403.        (generic-function-p function)
  404.        (generic-function-name function))
  405.       (funcall *old-function-name* function)))
  406.  
  407. (eval-when (load)
  408.   (unless (boundp '*old-function-name*)
  409.     (setq *old-function-name* #'si:function-name)
  410.     (setf (symbol-function 'si:function-name) 'new-function-name)))
  411.  
  412. ;;;
  413. ;;; This code is adapted from frame-lexical-environment and frame-function.
  414. ;;;
  415. #||
  416. dbg:
  417. (progn
  418.  
  419. (defvar *old-frame-function*)
  420.  
  421. (defvar *inside-new-frame-function* nil)
  422.  
  423. (defun new-frame-function (frame)
  424.   (let* ((fn (funcall *old-frame-function* frame))
  425.      (location (%pointer-plus frame #+imach (defstorage-size stack-frame) #-imach 0))
  426.      (env? #+3600 (location-contents location)
  427.            #+imach (%memory-read location :cycle-type %memory-scavenge)))
  428.     (or (when (cl:consp env?)
  429.       (let ((l2 (last2 env?)))
  430.         (when (eq (car l2) '.this-is-a-dfun.)
  431.           (cadr l2))))
  432.     fn)))
  433.  
  434. (defun pcl::doctor-dfun-for-the-debugger (gf dfun)
  435.   (when (sys:lexical-closure-p dfun)
  436.     (let* ((env (si:lexical-closure-environment dfun))
  437.        (l2 (last2 env)))
  438.       (unless (eq (car l2) '.this-is-a-dfun.)
  439.     (setf (si:lexical-closure-environment dfun)
  440.           (nconc env (list '.this-is-a-dfun. gf))))))
  441.   dfun)
  442.  
  443. (defun last2 (l)
  444.   (labels ((scan (2ago tail)
  445.          (if (null tail)
  446.          2ago
  447.          (if (cl:consp tail)
  448.              (scan (cdr 2ago) (cdr tail))
  449.              nil))))
  450.     (and (cl:consp l)
  451.      (cl:consp (cdr l))
  452.      (scan l (cddr l)))))
  453.  
  454. (eval-when (load)
  455.   (unless (boundp '*old-frame-function*)
  456.     (setq *old-frame-function* #'frame-function)
  457.     (setf (cl:symbol-function 'frame-function) 'new-frame-function)))
  458.  
  459. )
  460. ||#
  461.  
  462. (defvar *old-arglist*)
  463.  
  464. (defun pcl-arglist (function &rest other-args)
  465.   (let ((defn nil))
  466.     (cond ((and (fsc-instance-p function)
  467.         (generic-function-p function))
  468.        (generic-function-pretty-arglist function))
  469.       ((and (sys:validate-function-spec function)
  470.         (sys:fdefinedp function)
  471.         (setq defn (sys:fdefinition function))
  472.         (fsc-instance-p defn)
  473.         (generic-function-p defn))
  474.        (generic-function-pretty-arglist defn))
  475.       (t (apply *old-arglist* function other-args)))))
  476.  
  477. (eval-when (eval load)
  478.   (unless (boundp '*old-arglist*)
  479.     (setq *old-arglist* (symbol-function 'zl:arglist))
  480.     (setf (symbol-function 'zl:arglist) #'pcl-arglist)))
  481.  
  482.  
  483. (defvar *old-function-name*)
  484.  
  485. (defun pcl-function-name (function &rest other-args)
  486.   (if (and (fsc-instance-p function)
  487.        (generic-function-p function))
  488.       (generic-function-name function)
  489.       (apply *old-function-name* function other-args)))
  490.  
  491. (eval-when (eval load)
  492.   (unless (boundp '*old-function-name*)
  493.     (setq *old-function-name* (symbol-function 'si:function-name))
  494.     (setf (symbol-function 'si:function-name) #'pcl-function-name)))
  495.  
  496.  
  497. );end of #+Genera
  498.  
  499.  
  500.  
  501. ;;;
  502. ;;; In Genera 8.0, we use a real funcallable instance (from Genera CLOS) for this.
  503. ;;; This minimizes the subprimitive mucking around.
  504. ;;;
  505. #+(and Genera Genera-Release-8)
  506. (progn
  507.  
  508. (clos-internals::ensure-class
  509.   'pcl-funcallable-instance
  510.   :direct-superclasses '(clos-internals:funcallable-instance)
  511.   :slots `((:name function
  512.         :initform #'(lambda (ignore &rest ignore-them-too)
  513.               (declare (ignore ignore ignore-them-too))
  514.               (called-fin-without-function))
  515.         :initfunction ,#'(lambda nil
  516.                    #'(lambda (ignore &rest ignore-them-too)
  517.                    (declare (ignore ignore ignore-them-too))
  518.                    (called-fin-without-function))))
  519.        ,@(mapcar #'(lambda (slot) `(:name ,slot)) funcallable-instance-data))
  520.   :metaclass 'clos:funcallable-standard-class)
  521.  
  522. (defun pcl-funcallable-instance-trampoline (extra-arg &rest args)
  523.   (apply (sys:%instance-ref (clos-internals::%dispatch-instance-from-extra-argument extra-arg)
  524.                 3)
  525.      args))
  526.  
  527. (defun allocate-funcallable-instance-1 ()
  528.   (let ((fin (clos:make-instance 'pcl-funcallable-instance)))
  529.     (setf (clos-internals::%funcallable-instance-function fin)
  530.       #'pcl-funcallable-instance-trampoline)
  531.     (setf (clos-internals::%funcallable-instance-extra-argument fin)
  532.       (sys:%make-pointer sys:dtp-instance
  533.                  (clos-internals::%funcallable-instance-extra-argument fin)))
  534.     (setf (clos:slot-value fin 'clos-internals::funcallable-instance) fin)
  535.     fin))
  536.  
  537. (scl:defsubst funcallable-instance-p (x)
  538.   (and (sys:funcallable-instance-p x)
  539.        (eq (clos-internals::%funcallable-instance-function x)
  540.        #'pcl-funcallable-instance-trampoline)))
  541.  
  542. (defun set-funcallable-instance-function (fin new-value)
  543.   (setf (clos:slot-value fin 'function) new-value))
  544.  
  545. (defmacro funcallable-instance-data-1 (fin data)
  546.   `(clos-internals:%funcallable-instance-ref
  547.      ,fin (+ 4 (funcallable-instance-data-position ,data))))
  548.  
  549. (defsetf funcallable-instance-data-1 (fin data) (new-value)
  550.   `(setf (clos-internals:%funcallable-instance-ref
  551.        ,fin (+ 4 (funcallable-instance-data-position ,data)))
  552.      ,new-value))
  553.  
  554. (clos:defmethod clos:print-object ((fin pcl-funcallable-instance) stream)
  555.   (print-object fin stream))
  556.  
  557. (clos:defmethod clos-internals:debugging-information-function ((fin pcl-funcallable-instance))
  558.   nil)
  559.  
  560. (clos:defmethod clos-internals:function-name-object ((fin pcl-funcallable-instance))
  561.   (declare (special *boot-state*))
  562.   (if (and (eq *boot-state* 'complete)
  563.        (generic-function-p fin))
  564.       (generic-function-name fin)
  565.       fin))
  566.  
  567. (clos:defmethod clos-internals:arglist-object ((fin pcl-funcallable-instance))
  568.   (declare (special *boot-state*))
  569.   (if (and (eq *boot-state* 'complete)
  570.        (generic-function-p fin))
  571.       (generic-function-pretty-arglist fin)
  572.       '(&rest args)))
  573.  
  574. );end of #+Genera
  575.  
  576.  
  577.  
  578. #+Cloe-Runtime
  579. (progn
  580.  
  581. (defconstant funcallable-instance-closure-slots 5)
  582. (defconstant funcallable-instance-closure-size
  583.          (+ funcallable-instance-closure-slots (length funcallable-instance-data) 1))
  584.  
  585. #-CLOE-Release-2 (progn
  586.  
  587. (defun allocate-funcallable-instance-1 ()
  588.   (let ((data (system::make-funcallable-structure 'funcallable-instance
  589.                           funcallable-instance-closure-size)))
  590.     (setf (system::%trampoline-ref data funcallable-instance-closure-slots)
  591.       'funcallable-instance)
  592.     (set-funcallable-instance-function
  593.       data
  594.       #'(lambda (&rest ignore-them-too)
  595.       (declare (ignore ignore-them-too))
  596.       (called-fin-without-function)))
  597.     data))
  598.  
  599. (proclaim '(inline funcallable-instance-p))
  600. (defun funcallable-instance-p (x)
  601.   (and (typep x 'system::trampoline)
  602.        (= (system::%trampoline-data-length x) funcallable-instance-closure-size)
  603.        (eq (system::%trampoline-ref x funcallable-instance-closure-slots)
  604.        'funcallable-instance)))
  605.  
  606. (defun set-funcallable-instance-function (fin new-value)
  607.   (when (not (funcallable-instance-p fin))
  608.     (error "~S is not a funcallable-instance" fin))
  609.   (etypecase new-value
  610.     (system::trampoline
  611.       (let ((length (system::%trampoline-data-length new-value)))
  612.     (cond ((> length funcallable-instance-closure-slots)
  613.            (set-funcallable-instance-function
  614.          fin
  615.          #'(lambda (&rest args)
  616.              (declare (sys:downward-rest-argument))
  617.              (apply new-value args))))
  618.           (t
  619.            (setf (system::%trampoline-function fin)
  620.              (system::%trampoline-function new-value))
  621.            (dotimes (i length)
  622.          (setf (system::%trampoline-ref fin i)
  623.                (system::%trampoline-ref new-value i)))))))
  624.     (compiled-function
  625.       (setf (system::%trampoline-function fin) new-value))
  626.     (function
  627.       (set-funcallable-instance-function
  628.     fin
  629.     #'(lambda (&rest args)
  630.         (declare (sys:downward-rest-argument))
  631.         (apply new-value args))))))
  632.  
  633. (defmacro funcallable-instance-data-1 (fin data)
  634.   `(system::%trampoline-ref ,fin (+ funcallable-instance-closure-slots
  635.                     1 (funcallable-instance-data-position ,data))))
  636.  
  637. (defsetf funcallable-instance-data-1 (fin data) (new-value)
  638.   `(setf (system::%trampoline-ref ,fin (+ funcallable-instance-closure-slots
  639.                       1 (funcallable-instance-data-position ,data)))
  640.      ,new-value))
  641.  
  642. )
  643.  
  644. #+CLOE-Release-2 (progn
  645.  
  646. (defun allocate-funcallable-instance-1 ()
  647.   (let ((data (si::cons-closure funcallable-instance-closure-size)))
  648.     (setf (si::closure-ref data funcallable-instance-closure-slots) 'funcallable-instance)
  649.     (set-funcallable-instance-function
  650.       data
  651.       #'(lambda (&rest ignore-them-too)
  652.       (declare (ignore ignore-them-too))
  653.       (error "Called a FIN without first setting its function.")))
  654.     data))
  655.  
  656. (proclaim '(inline funcallable-instance-p))
  657. (defun funcallable-instance-p (x)
  658.   (and (si::closurep x)
  659.        (= (si::closure-length x) funcallable-instance-closure-size)
  660.        (eq (si::closure-ref x funcallable-instance-closure-slots) 'funcallable-instance)))
  661.  
  662. (defun set-funcallable-instance-function (fin new-value)
  663.   (when (not (funcallable-instance-p fin))
  664.     (error "~S is not a funcallable-instance" fin))
  665.   (etypecase new-value
  666.     (si::closure
  667.       (let ((length (si::closure-length new-value)))
  668.     (cond ((> length funcallable-instance-closure-slots)
  669.            (set-funcallable-instance-function
  670.          fin
  671.          #'(lambda (&rest args)
  672.              (declare (sys:downward-rest-argument))
  673.              (apply new-value args))))
  674.           (t
  675.            (setf (si::closure-function fin) (si::closure-function new-value))
  676.            (dotimes (i length)
  677.          (si::object-set fin (+ i 3) (si::object-ref new-value (+ i 3))))))))
  678.     (compiled-function
  679.       (setf (si::closure-function fin) new-value))
  680.     (function
  681.       (set-funcallable-instance-function
  682.     fin
  683.     #'(lambda (&rest args)
  684.         (declare (sys:downward-rest-argument))
  685.         (apply new-value args))))))
  686.  
  687. (defmacro funcallable-instance-data-1 (fin data)
  688.   `(si::closure-ref ,fin (+ funcallable-instance-closure-slots
  689.                 1 (funcallable-instance-data-position ,data))))
  690.  
  691. (defsetf funcallable-instance-data-1 (fin data) (new-value)
  692.   `(setf (si::closure-ref ,fin (+ funcallable-instance-closure-slots
  693.                   1 (funcallable-instance-data-position ,data)))
  694.      ,new-value))
  695.  
  696. )
  697.  
  698. )
  699.  
  700.  
  701. ;;;
  702. ;;;
  703. ;;; In Xerox Common Lisp, a lexical closure is a pair of an environment and
  704. ;;; CCODEP.  The environment is represented as a block.  There is space in
  705. ;;; the top 8 bits of the pointers to the CCODE and the environment to use
  706. ;;; to mark the closure as being a FIN.
  707. ;;;
  708. ;;; To help the debugger figure out when it has found a FIN on the stack, we
  709. ;;; reserve the last element of the closure environment to use to point back
  710. ;;; to the actual fin.
  711. ;;;
  712. ;;; Note that there is code in xerox-low which lets us access the fields of
  713. ;;; compiled-closures and which defines the closure-overlay record.  That
  714. ;;; code is there because there are some clients of it in that file.
  715. ;;;      
  716. #+Xerox
  717. (progn
  718.  
  719. ;; Don't be fooled.  We actually allocate one bigger than this to have a place
  720. ;; to store the backpointer to the fin.  -smL
  721. (defconstant funcallable-instance-closure-size 15)
  722.  
  723. ;; This is only used in the file PCL-ENV.
  724. (defvar *fin-env-type*
  725.   (type-of (il:\\allocblock (1+ funcallable-instance-closure-size) t)))
  726.  
  727. ;; Well, Gregor may be too proud to hack xpointers, but bvm and I aren't. -smL
  728.  
  729. (defstruct fin-env-pointer
  730.   (pointer nil :type il:fullxpointer))
  731.  
  732. (defun fin-env-fin (fin-env)
  733.   (fin-env-pointer-pointer
  734.    (il:\\getbaseptr fin-env (* funcallable-instance-closure-size 2))))
  735.  
  736. (defun |set fin-env-fin| (fin-env new-value)
  737.   (il:\\rplptr fin-env (* funcallable-instance-closure-size 2)
  738.            (make-fin-env-pointer :pointer new-value))
  739.   new-value)
  740.  
  741. (defsetf fin-env-fin |set fin-env-fin|)
  742.  
  743. ;; The finalization function that will clean up the backpointer from the
  744. ;; fin-env to the fin.  This needs to be careful to not cons at all.  This
  745. ;; depends on there being no other finalization function on compiled-closures,
  746. ;; since there is only one finalization function per datatype.  Too bad.  -smL
  747. (defun finalize-fin (fin)
  748.   ;; This could use the fn funcallable-instance-p, but if we get here we know
  749.   ;; that this is a closure, so we can skip that test.
  750.   (when (il:fetch (closure-overlay funcallable-instance-p) il:of fin)
  751.     (let ((env (il:fetch (il:compiled-closure il:environment) il:of fin)))
  752.       (when env
  753.     (setq env
  754.           (il:\\getbaseptr env (* funcallable-instance-closure-size 2)))
  755.     (when (il:typep env 'fin-env-pointer) 
  756.       (setf (fin-env-pointer-pointer env) nil)))))
  757.   nil)                    ;Return NIL so GC can proceed
  758.  
  759. (eval-when (load)
  760.   ;; Install the above finalization function.
  761.   (when (fboundp 'finalize-fin)
  762.     (il:\\set.finalization.function 'il:compiled-closure 'finalize-fin)))
  763.  
  764. (defun allocate-funcallable-instance-1 ()
  765.   (let* ((env (il:\\allocblock (1+ funcallable-instance-closure-size) t))
  766.          (fin (il:make-compiled-closure nil env)))
  767.     (setf (fin-env-fin env) fin)
  768.     (il:replace (closure-overlay funcallable-instance-p) il:of fin il:with 't)
  769.     (set-funcallable-instance-function fin
  770.       #'(lambda (&rest ignore)
  771.           (declare (ignore ignore))
  772.       (called-fin-without-function)))
  773.     fin))
  774.  
  775. (xcl:definline funcallable-instance-p (x)
  776.   (and (typep x 'il:compiled-closure)
  777.        (il:fetch (closure-overlay funcallable-instance-p) il:of x)))
  778.  
  779. (defun set-funcallable-instance-function (fin new)
  780.   (cond ((not (funcallable-instance-p fin))
  781.          (error "~S is not a funcallable-instance" fin))
  782.         ((not (functionp new))
  783.          (error "~S is not a function." new))
  784.         ((typep new 'il:compiled-closure)
  785.          (let* ((fin-env
  786.                   (il:fetch (il:compiled-closure il:environment) il:of fin))
  787.                 (new-env
  788.                   (il:fetch (il:compiled-closure il:environment) il:of new))
  789.                 (new-env-size (if new-env (il:\\#blockdatacells new-env) 0))
  790.                 (fin-env-size (- funcallable-instance-closure-size
  791.                                  (length funcallable-instance-data))))
  792.            (cond ((and new-env
  793.                (<= new-env-size fin-env-size))
  794.           (dotimes (i fin-env-size)
  795.             (il:\\rplptr fin-env
  796.                  (* i 2)
  797.                  (if (< i new-env-size)
  798.                      (il:\\getbaseptr new-env (* i 2))
  799.                      nil)))
  800.           (setf (compiled-closure-fnheader fin)
  801.             (compiled-closure-fnheader new)))
  802.                  (t
  803.                   (set-funcallable-instance-function
  804.                     fin
  805.                     (make-trampoline new))))))
  806.         (t
  807.          (set-funcallable-instance-function fin
  808.                                             (make-trampoline new)))))
  809.  
  810. (defun make-trampoline (function)
  811.   #'(lambda (&rest args)
  812.       (apply function args)))
  813.  
  814.         
  815. (defmacro funcallable-instance-data-1 (fin data)
  816.   `(il:\\getbaseptr (il:fetch (il:compiled-closure il:environment) il:of ,fin)
  817.             (* (- funcallable-instance-closure-size
  818.               (funcallable-instance-data-position ,data)
  819.               1)            ;Reserve last element to
  820.                         ;point back to actual FIN!
  821.                2)))
  822.  
  823. (defsetf funcallable-instance-data-1 (fin data) (new-value)
  824.   `(il:\\rplptr (il:fetch (il:compiled-closure il:environment) il:of ,fin)
  825.         (* (- funcallable-instance-closure-size
  826.               (funcallable-instance-data-position ,data)
  827.               1)
  828.            2)
  829.         ,new-value))
  830.  
  831. );end of #+Xerox
  832.  
  833.  
  834. ;;;
  835. ;;; In Franz Common Lisp ExCL
  836. ;;; This code was originally written by:
  837. ;;;   jkf%franz.uucp@berkeley.edu
  838. ;;; and hacked by:
  839. ;;;   smh%franz.uucp@berkeley.edu
  840.  
  841. #+ExCL
  842. (progn
  843.  
  844. (defconstant funcallable-instance-flag-bit #x1)
  845.  
  846. (defun funcallable-instance-p (x)
  847.    (and (excl::function-object-p x)
  848.         (eq funcallable-instance-flag-bit
  849.             (logand (excl::fn_flags x)
  850.                     funcallable-instance-flag-bit))))
  851.  
  852. (defun make-trampoline (function)
  853.   #'(lambda (&rest args)
  854.       (apply function args)))
  855.  
  856. ;; We initialize a fin's procedure function to this because
  857. ;; someone might try to funcall it before it has been set up.
  858. (defun init-fin-fun (&rest ignore)
  859.   (declare (ignore ignore))
  860.   (called-fin-without-function))
  861.  
  862.  
  863. (eval-when (eval) 
  864.   (compile 'make-trampoline)
  865.   (compile 'init-fin-fun))
  866.  
  867.  
  868. ;; new style
  869. #+(and gsgc (not sun4) (not cray) (not mips))
  870. (progn
  871. ;; set-funcallable-instance-function must work by overwriting the fin itself
  872. ;; because the fin must maintain EQ identity.
  873. ;; Because the gsgc time needs several of the fields in the function object
  874. ;; at gc time in order to walk the stack frame, it is important never to bash
  875. ;; a function object that is active in a frame on the stack.  Besides, changing
  876. ;; the functions closure vector, not to mention overwriting its constant
  877. ;; vector, would scramble it's execution when that stack frame continues.
  878. ;; Therefore we represent a fin as a funny compiled-function object.
  879. ;; The code vector of this object has some hand-coded instructions which
  880. ;; do a very fast jump into the real fin handler function.  The function
  881. ;; which is the fin object *never* creates a frame on the stack.
  882.   
  883.  
  884. (defun allocate-funcallable-instance-1 ()
  885.   (let ((fin (compiler::.primcall 'sys::new-function))
  886.     (init #'init-fin-fun)
  887.     (mattress-fun #'funcallable-instance-mattress-pad))
  888.     (setf (excl::fn_symdef fin) 'anonymous-fin)
  889.     (setf (excl::fn_constant fin) init)
  890.     (setf (excl::fn_code fin)        ; this must be before fn_start
  891.       (excl::fn_code mattress-fun))
  892.     (setf (excl::fn_start fin) (excl::fn_start mattress-fun))
  893.     (setf (excl::fn_flags fin) (logior (excl::fn_flags init)
  894.                        funcallable-instance-flag-bit))
  895.     (setf (excl::fn_closure fin)
  896.       (make-array (length funcallable-instance-data)))
  897.  
  898.     fin))
  899.  
  900. ;; This function gets its code vector modified with a hand-coded fast jump
  901. ;; to the function that is stored in place oplits constant vector.
  902. ;; This function is never linked in and never appears on the stack.
  903.  
  904. (defun funcallable-instance-mattress-pad ()
  905.   (declare (optimize (speed 3) (safety 0)))
  906.   'nil)
  907.  
  908. (eval-when (eval)
  909.   (compile 'funcallable-instance-mattress-pad))
  910.  
  911.  
  912. #+(and excl (target-class s))
  913. (eval-when (load eval)
  914.   (let ((codevec (excl::fn_code
  915.           (symbol-function 'funcallable-instance-mattress-pad))))
  916.     ;; The entire code vector wants to be:
  917.     ;;   move.l  7(a2),a2     ;#x246a0007
  918.     ;;   jmp     1(a2)        ;#x4eea0001
  919.     (setf (aref codevec 0) #x246a
  920.       (aref codevec 1) #x0007
  921.       (aref codevec 2) #x4eea
  922.       (aref codevec 3) #x0001))
  923. )
  924.  
  925. #+(and excl (target-class a))
  926. (eval-when (load eval)
  927.   (let ((codevec (excl::fn_code
  928.           (symbol-function 'funcallable-instance-mattress-pad))))
  929.     ;; The entire code vector wants to be:
  930.     ;;   l       r5,15(r5)    ;#x5850500f
  931.     ;;   l       r15,11(r5)   ;#x58f0500b
  932.     ;;   br      r15          ;#x07ff
  933.     (setf (aref codevec 0) #x5850
  934.       (aref codevec 1) #x500f
  935.       (aref codevec 2) #x58f0
  936.       (aref codevec 3) #x500b
  937.       (aref codevec 4) #x07ff
  938.       (aref codevec 5) #x0000))
  939.   )
  940.  
  941. #+(and excl (target-class i))
  942. (eval-when (load eval)
  943.   (let ((codevec (excl::fn_code
  944.           (symbol-function 'funcallable-instance-mattress-pad))))
  945.     ;; The entire code vector wants to be:
  946.     ;;   movl  7(edx),edx     ;#x07528b
  947.     ;;   jmp   *3(edx)        ;#x0362ff
  948.     (setf (aref codevec 0) #x8b
  949.       (aref codevec 1) #x52
  950.       (aref codevec 2) #x07
  951.       (aref codevec 3) #xff
  952.       (aref codevec 4) #x62
  953.       (aref codevec 5) #x03))
  954. )
  955.  
  956. (defun funcallable-instance-data-1 (instance data)
  957.   (let ((constant (excl::fn_closure instance)))
  958.     (svref constant (funcallable-instance-data-position data))))
  959.  
  960. (defsetf funcallable-instance-data-1 set-funcallable-instance-data-1)
  961.  
  962. (defun set-funcallable-instance-data-1 (instance data new-value)
  963.   (let ((constant (excl::fn_closure instance)))
  964.     (setf (svref constant (funcallable-instance-data-position data))
  965.           new-value)))
  966.  
  967. (defun set-funcallable-instance-function (fin new-function)
  968.   (unless (funcallable-instance-p fin)
  969.     (error "~S is not a funcallable-instance" fin))
  970.   (unless (functionp new-function)
  971.     (error "~S is not a function." new-function))
  972.   (setf (excl::fn_constant fin)
  973.     (if (excl::function-object-p new-function)
  974.         new-function
  975.         ;; The new-function is an interpreted function.
  976.         ;; Install a trampoline to call the interpreted function.
  977.         (make-trampoline new-function))))
  978.  
  979.  
  980. )  ;; end sun3
  981.  
  982.  
  983. #+(and gsgc (or sun4 mips))
  984. (progn
  985.  
  986. (eval-when (compile load eval)
  987.   (defconstant funcallable-instance-constant-count 15)
  988.   )
  989.  
  990. (defun allocate-funcallable-instance-1 ()
  991.   (let ((new-fin (compiler::.primcall 
  992.            'sys::new-function
  993.            funcallable-instance-constant-count)))
  994.     ;; Have to set the procedure function to something for two reasons.
  995.     ;;   1. someone might try to funcall it.
  996.     ;;   2. the flag bit that says the procedure is a funcallable
  997.     ;;      instance is set by set-funcallable-instance-function.
  998.     (set-funcallable-instance-function new-fin #'init-fin-fun)
  999.     new-fin))
  1000.  
  1001. (defun set-funcallable-instance-function (fin new-value)
  1002.   ;; we actually only check for a function object since
  1003.   ;; this is called before the funcallable instance flag is set
  1004.   (unless (excl::function-object-p fin)
  1005.     (error "~S is not a funcallable-instance" fin))
  1006.  
  1007.   (cond ((not (functionp new-value))
  1008.          (error "~S is not a function." new-value))
  1009.         ((not (excl::function-object-p new-value))
  1010.          ;; new-value is an interpreted function.  Install a
  1011.          ;; trampoline to call the interpreted function.
  1012.          (set-funcallable-instance-function fin (make-trampoline new-value)))
  1013.     ((> (+ (excl::function-constant-count new-value)
  1014.            (length funcallable-instance-data))
  1015.         funcallable-instance-constant-count)
  1016.      ; can't fit, must trampoline
  1017.      (set-funcallable-instance-function fin (make-trampoline new-value)))
  1018.         (t
  1019.          ;; tack the instance variables at the end of the constant vector
  1020.      
  1021.          (setf (excl::fn_code fin)    ; this must be before fn_start
  1022.            (excl::fn_code new-value))
  1023.          (setf (excl::fn_start fin) (excl::fn_start new-value))
  1024.          
  1025.          (setf (excl::fn_closure fin) (excl::fn_closure new-value))
  1026.      ; only replace the symdef slot if the new value is an 
  1027.      ; interned symbol or some other object (like a function spec)
  1028.      (let ((newsym (excl::fn_symdef new-value)))
  1029.        (excl:if* (and newsym (or (not (symbolp newsym))
  1030.                 (symbol-package newsym)))
  1031.           then (setf (excl::fn_symdef fin) newsym)))
  1032.          (setf (excl::fn_formals fin) (excl::fn_formals new-value))
  1033.          (setf (excl::fn_cframe-size fin) (excl::fn_cframe-size new-value))
  1034.      (setf (excl::fn_locals fin) (excl::fn_locals new-value))
  1035.          (setf (excl::fn_flags fin) (logior (excl::fn_flags new-value)
  1036.                                             funcallable-instance-flag-bit))
  1037.      
  1038.      ;; on a sun4 we copy over the constants
  1039.      (dotimes (i (excl::function-constant-count new-value))
  1040.        (setf (excl::function-constant fin i) 
  1041.          (excl::function-constant new-value i)))
  1042.      ;(format t "all done copy from ~s to ~s" new-value fin)
  1043.      )))
  1044.  
  1045. (defmacro funcallable-instance-data-1 (instance data)
  1046.   `(excl::function-constant ,instance 
  1047.                (- funcallable-instance-constant-count
  1048.                   (funcallable-instance-data-position ,data)
  1049.                   1)))
  1050.  
  1051. ) ;; end sun4 or mips
  1052.  
  1053. #+(and gsgc cray)
  1054. (progn
  1055.  
  1056. ;; The cray is like the sun4 in that the constant vector is included in the  
  1057. ;; function object itself.  But a mattress pad must be used anyway, because
  1058. ;; the function start address is copied in the symbol object, and cannot be
  1059. ;; updated when the fin is changed.  
  1060. ;; We place the funcallable-instance-function into the first constant slot,  
  1061. ;; and leave enough constant slots after that for the instance data.
  1062.  
  1063. (eval-when (compile load eval)
  1064.   (defconstant fin-fun-slot 0)
  1065.   (defconstant fin-instance-data-slot 1)
  1066.   )
  1067.  
  1068.  
  1069. ;; We initialize a fin's procedure function to this because
  1070. ;; someone might try to funcall it before it has been set up.
  1071. (defun init-fin-fun (&rest ignore)
  1072.   (declare (ignore ignore))
  1073.   (called-fin-without-function))
  1074.  
  1075. (defun allocate-funcallable-instance-1 ()
  1076.   (let ((fin (compiler::.primcall 'sys::new-function
  1077.             (1+ (length funcallable-instance-data))
  1078.             "funcallable-instance"))
  1079.     (init #'init-fin-fun)
  1080.     (mattress-fun #'funcallable-instance-mattress-pad))
  1081.     (setf (excl::fn_symdef fin) 'anonymous-fin)
  1082.     (setf (excl::function-constant fin fin-fun-slot) init)
  1083.     (setf (excl::fn_code fin)        ; this must be before fn_start
  1084.       (excl::fn_code mattress-fun))
  1085.     (setf (excl::fn_start fin) (excl::fn_start mattress-fun))
  1086.     (setf (excl::fn_flags fin) (logior (excl::fn_flags init)
  1087.                        funcallable-instance-flag-bit))
  1088.     
  1089.     fin))
  1090.  
  1091. ;; This function gets its code vector modified with a hand-coded fast jump
  1092. ;; to the function that is stored in place of its constant vector.
  1093. ;; This function is never linked in and never appears on the stack.
  1094.  
  1095. (defun funcallable-instance-mattress-pad ()
  1096.   (declare (optimize (speed 3) (safety 0)))
  1097.   'nil)
  1098.  
  1099. (eval-when (eval)
  1100.   (compile 'funcallable-instance-mattress-pad)
  1101.   (compile 'init-fin-fun))
  1102.  
  1103. (eval-when (load eval)
  1104.   (let ((codevec (excl::fn_code
  1105.           (symbol-function 'funcallable-instance-mattress-pad))))
  1106.     ;; The entire code vector wants to be:
  1107.     ;;   a1  b77
  1108.     ;;   a2  12,a1
  1109.     ;;   a1 1,a2
  1110.     ;;   b77 a2
  1111.     ;;   b76 a1
  1112.     ;;   j   b76
  1113.     (setf (aref codevec 0) #o024177
  1114.       (aref codevec 1) #o101200 (aref codevec 2) 12
  1115.       (aref codevec 3) #o102100 (aref codevec 4) 1
  1116.       (aref codevec 5) #o025277
  1117.       (aref codevec 6) #o025176
  1118.       (aref codevec 7) #o005076
  1119.       ))
  1120. )
  1121.  
  1122. (defmacro funcallable-instance-data-1 (instance data)
  1123.   `(excl::function-constant ,instance 
  1124.                 (+ (funcallable-instance-data-position ,data)
  1125.                    fin-instance-dtat-slot)))
  1126.  
  1127.  
  1128. (defun set-funcallable-instance-function (fin new-function)
  1129.   (unless (funcallable-instance-p fin)
  1130.     (error "~S is not a funcallable-instance" fin))
  1131.   (unless (functionp new-function)
  1132.     (error "~S is not a function." new-function))
  1133.   (setf (excl::function-constant fin fin-fun-slot)
  1134.     (if (excl::function-object-p new-function)
  1135.     new-function
  1136.     ;; The new-function is an interpreted function.
  1137.     ;; Install a trampoline to call the interpreted function.
  1138.     (make-trampoline new-function))))
  1139.  
  1140. ) ;; end cray
  1141.  
  1142. #-gsgc
  1143. (progn
  1144.  
  1145. (defun allocate-funcallable-instance-1 ()
  1146.   (let ((new-fin (compiler::.primcall 'sys::new-function)))
  1147.     ;; Have to set the procedure function to something for two reasons.
  1148.     ;;   1. someone might try to funcall it.
  1149.     ;;   2. the flag bit that says the procedure is a funcallable
  1150.     ;;      instance is set by set-funcallable-instance-function.
  1151.     (set-funcallable-instance-function new-fin #'init-fin-fn)
  1152.     new-fin))
  1153.  
  1154. (defun set-funcallable-instance-function (fin new-value)
  1155.   ;; we actually only check for a function object since
  1156.   ;; this is called before the funcallable instance flag is set
  1157.   (unless (excl::function-object-p fin)
  1158.     (error "~S is not a funcallable-instance" fin))
  1159.   (cond ((not (functionp new-value))
  1160.          (error "~S is not a function." new-value))
  1161.         ((not (excl::function-object-p new-value))
  1162.          ;; new-value is an interpreted function.  Install a
  1163.          ;; trampoline to call the interpreted function.
  1164.          (set-funcallable-instance-function fin (make-trampoline new-value)))
  1165.         (t
  1166.          ;; tack the instance variables at the end of the constant vector
  1167.          (setf (excl::fn_start fin) (excl::fn_start new-value))
  1168.          (setf (excl::fn_constant fin) (add-instance-vars
  1169.                                         (excl::fn_constant new-value)
  1170.                                         (excl::fn_constant fin)))
  1171.          (setf (excl::fn_closure fin) (excl::fn_closure new-value))
  1172.      ;; In versions prior to 2.0. comment the next line and any other
  1173.      ;; references to fn_symdef or fn_locals.
  1174.      (setf (excl::fn_symdef fin) (excl::fn_symdef new-value))
  1175.          (setf (excl::fn_code fin) (excl::fn_code new-value))
  1176.          (setf (excl::fn_formals fin) (excl::fn_formals new-value))
  1177.          (setf (excl::fn_cframe-size fin) (excl::fn_cframe-size new-value))
  1178.      (setf (excl::fn_locals fin) (excl::fn_locals new-value))
  1179.          (setf (excl::fn_flags fin) (logior (excl::fn_flags new-value)
  1180.                                             funcallable-instance-flag-bit)))))
  1181.  
  1182. (defun add-instance-vars (cvec old-cvec)
  1183.   ;; create a constant vector containing everything in the given constant
  1184.   ;; vector plus space for the instance variables
  1185.   (let* ((nconstants (cond (cvec (length cvec)) (t 0)))
  1186.          (ndata (length funcallable-instance-data))
  1187.          (old-cvec-length (if old-cvec (length old-cvec) 0))
  1188.          (new-cvec nil))
  1189.     (cond ((<= (+ nconstants ndata)  old-cvec-length)
  1190.            (setq new-cvec old-cvec))
  1191.           (t
  1192.            (setq new-cvec (make-array (+ nconstants ndata)))
  1193.            (when old-cvec
  1194.              (dotimes (i ndata)
  1195.                (setf (svref new-cvec (- (+ nconstants ndata) i 1))
  1196.                      (svref old-cvec (- old-cvec-length i 1)))))))
  1197.     
  1198.     (dotimes (i nconstants) (setf (svref new-cvec i) (svref cvec i)))
  1199.     
  1200.     new-cvec))
  1201.  
  1202. (defun funcallable-instance-data-1 (instance data)
  1203.   (let ((constant (excl::fn_constant instance)))
  1204.     (svref constant (- (length constant)
  1205.                        (1+ (funcallable-instance-data-position data))))))
  1206.  
  1207. (defsetf funcallable-instance-data-1 set-funcallable-instance-data-1)
  1208.  
  1209. (defun set-funcallable-instance-data-1 (instance data new-value)
  1210.   (let ((constant (excl::fn_constant instance)))
  1211.     (setf (svref constant (- (length constant) 
  1212.                              (1+ (funcallable-instance-data-position data))))
  1213.           new-value)))
  1214.  
  1215. );end #-gsgc
  1216.  
  1217. );end of #+ExCL
  1218.  
  1219.  
  1220. ;;;
  1221. ;;; In Vaxlisp
  1222. ;;; This code was originally written by:
  1223. ;;;    vanroggen%bach.DEC@DECWRL.DEC.COM
  1224. ;;; 
  1225. #+(and dec vax common)
  1226. (progn
  1227.  
  1228. ;;; The following works only in Version 2 of VAXLISP, and will have to
  1229. ;;; be replaced for later versions.
  1230.  
  1231. (defun allocate-funcallable-instance-1 ()
  1232.   (list 'system::%compiled-closure%
  1233.         ()
  1234.         #'(lambda (&rest args)
  1235.             (declare (ignore args))
  1236.         (called-fin-without-function))
  1237.         (make-array (length funcallable-instance-data))))
  1238.  
  1239. (proclaim '(inline funcallable-instance-p))
  1240. (defun funcallable-instance-p (x)
  1241.   (and (consp x)
  1242.        (eq (car x) 'system::%compiled-closure%)
  1243.        (not (null (cdddr x)))))
  1244.  
  1245. (defun set-funcallable-instance-function (fin func)
  1246.   (cond ((not (funcallable-instance-p fin))
  1247.          (error "~S is not a funcallable-instance" fin))
  1248.         ((not (functionp func))
  1249.          (error "~S is not a function" func))
  1250.         ((and (consp func) (eq (car func) 'system::%compiled-closure%))
  1251.          (setf (cadr fin) (cadr func)
  1252.                (caddr fin) (caddr func)))
  1253.         (t (set-funcallable-instance-function fin
  1254.                                               (make-trampoline func)))))
  1255.  
  1256. (defun make-trampoline (function)
  1257.   #'(lambda (&rest args)
  1258.       (apply function args)))
  1259.  
  1260. (eval-when (eval) (compile 'make-trampoline))
  1261.  
  1262. (defmacro funcallable-instance-data-1 (instance data)
  1263.   `(svref (cadddr ,instance)
  1264.           (funcallable-instance-data-position ,data)))
  1265.  
  1266. );end of Vaxlisp (and dec vax common)
  1267.  
  1268.  
  1269. ;;; Implementation of funcallable instances for CMU Common Lisp.
  1270. ;;;
  1271. ;;; Similiar to the code for VAXLISP implementation.
  1272. #+:CMU
  1273. (progn
  1274.  
  1275. (defun allocate-funcallable-instance-1 ()
  1276.   `(lisp::%compiled-closure%
  1277.      ()
  1278.      ,#'(lambda (&rest args)
  1279.       (declare (ignore args))
  1280.       (called-fin-without-function))
  1281.      ,(make-array (length funcallable-instance-data))))
  1282.  
  1283. (proclaim '(inline funcallable-instance-p))
  1284. (defun funcallable-instance-p (x)
  1285.   (and (consp x)
  1286.        (eq (car x) 'lisp::%compiled-closure%)
  1287.        (not (null (cdddr x)))))
  1288.  
  1289. (defun set-funcallable-instance-function (fin func)
  1290.   (cond ((not (funcallable-instance-p fin))
  1291.      (error "~S is not a funcallable-instance" fin))
  1292.     ((not (functionp func))
  1293.      (error "~S is not a function" func))
  1294.     ((and (consp func) (eq (car func) 'lisp::%compiled-closure%))
  1295.      (setf (cadr fin) (cadr func)
  1296.            (caddr fin) (caddr func)))
  1297.     (t (set-funcallable-instance-function fin
  1298.                           (make-trampoline func)))))
  1299.  
  1300. (defun make-trampoline (function)
  1301.   #'(lambda (&rest args)
  1302.       (apply function args)))
  1303.  
  1304. (eval-when (eval) (compile 'make-trampoline))
  1305.  
  1306. (defmacro funcallable-instance-data-1 (instance data)
  1307.   `(svref (cadddr ,instance)
  1308.       (funcallable-instance-data-position ,data)))
  1309.  
  1310. ); End of :CMU
  1311.  
  1312.  
  1313.  
  1314. ;;;
  1315. ;;; Kyoto Common Lisp (KCL)
  1316. ;;;
  1317. ;;; In KCL, compiled functions and compiled closures are defined as c structs.
  1318. ;;; This means that in order to access their fields, we have to use C code!
  1319. ;;; The C code we call and the lisp interface to it is in the file kcl-low.
  1320. ;;; The lisp interface to this code implements accessors to compiled closures
  1321. ;;; and compiled functions of about the same level of abstraction as that
  1322. ;;; which is used by the other implementation dependent versions of FINs in
  1323. ;;; this file.
  1324. ;;;
  1325.  
  1326. #+(and KCL (not IBCL))
  1327. (progn
  1328.  
  1329. (defvar *funcallable-instance-marker* (list "Funcallable Instance Marker"))
  1330.  
  1331. (defconstant funcallable-instance-closure-size 15)
  1332.  
  1333. (defconstant funcallable-instance-closure-size1
  1334.   (1- funcallable-instance-closure-size))
  1335.  
  1336. (defconstant funcallable-instance-available-size
  1337.   (- funcallable-instance-closure-size1
  1338.      (length funcallable-instance-data)))
  1339.  
  1340. (defmacro funcallable-instance-marker (x)
  1341.   `(car (cclosure-env-nthcdr funcallable-instance-closure-size1 ,x)))
  1342.  
  1343. (defun allocate-funcallable-instance-1 ()
  1344.   (let ((fin (allocate-funcallable-instance-2))
  1345.         (env (make-list funcallable-instance-closure-size :initial-element nil)))
  1346.     (setf (%cclosure-env fin) env)
  1347.     #+:turbo-closure (si:turbo-closure fin)
  1348.     (setf (funcallable-instance-marker fin) *funcallable-instance-marker*)
  1349.     fin))
  1350.  
  1351. (defun allocate-funcallable-instance-2 ()
  1352.   (let ((what-a-dumb-closure-variable ()))
  1353.     #'(lambda (&rest args)
  1354.         (declare (ignore args))
  1355.         (called-fin-without-function)
  1356.         (setq what-a-dumb-closure-variable
  1357.               (dummy-function what-a-dumb-closure-variable)))))
  1358.  
  1359. (defun funcallable-instance-p (x)
  1360.   (eq *funcallable-instance-marker* (funcallable-instance-marker x)))
  1361.  
  1362. (si:define-compiler-macro funcallable-instance-p (x)
  1363.   `(eq *funcallable-instance-marker* (funcallable-instance-marker ,x)))
  1364.  
  1365. (defun set-funcallable-instance-function (fin new-value)
  1366.   (cond ((not (funcallable-instance-p fin))
  1367.          (error "~S is not a funcallable-instance" fin))
  1368.         ((not (functionp new-value))
  1369.          (error "~S is not a function." new-value))
  1370.         ((and (cclosurep new-value)
  1371.               (<= (length (%cclosure-env new-value))
  1372.                   funcallable-instance-available-size))
  1373.          (%set-cclosure fin new-value funcallable-instance-available-size))
  1374.         (t
  1375.          (set-funcallable-instance-function
  1376.            fin (make-trampoline new-value))))
  1377.   fin)
  1378.  
  1379. (defmacro funcallable-instance-data-1 (fin data &environment env)
  1380.   ;; The compiler won't expand macros before deciding on optimizations,
  1381.   ;; so we must do it here.
  1382.   (let* ((pos-form (macroexpand `(funcallable-instance-data-position ,data)
  1383.                                 env))
  1384.          (index-form (if (constantp pos-form)
  1385.                          (- funcallable-instance-closure-size
  1386.                             (eval pos-form)
  1387.                             2)
  1388.                          `(- funcallable-instance-closure-size
  1389.                              (funcallable-instance-data-position ,data)
  1390.                              2))))
  1391.     `(car (%cclosure-env-nthcdr ,index-form ,fin))))
  1392.  
  1393.  
  1394. #+turbo-closure (clines "#define TURBO_CLOSURE")
  1395.  
  1396. (clines "
  1397. static make_trampoline_internal();
  1398. static make_turbo_trampoline_internal();
  1399.  
  1400. static object
  1401. make_trampoline(function)
  1402.      object function;
  1403. {
  1404.   vs_push(MMcons(function,Cnil));
  1405. #ifdef TURBO_CLOSURE
  1406.   if(type_of(function)==t_cclosure)
  1407.     {if(function->cc.cc_turbo==NULL)turbo_closure(function);
  1408.      vs_head=make_cclosure(make_turbo_trampoline_internal,Cnil,vs_head,Cnil,NULL,0);
  1409.      return vs_pop;}
  1410. #endif
  1411.   vs_head=make_cclosure(make_trampoline_internal,Cnil,vs_head,Cnil,NULL,0);
  1412.   return vs_pop;
  1413. }
  1414.  
  1415. static
  1416. make_trampoline_internal(base0)
  1417.      object *base0;
  1418. {super_funcall_no_event(base0[0]->c.c_car);}
  1419.  
  1420. static
  1421. make_turbo_trampoline_internal(base0)
  1422.      object *base0;
  1423. { object function=base0[0]->c.c_car;
  1424.   (*function->cc.cc_self)(function->cc.cc_turbo);
  1425. }
  1426.  
  1427. ")
  1428.  
  1429. (defentry make-trampoline (object) (object make_trampoline))
  1430. )
  1431.  
  1432. #+IBCL
  1433. (progn ; From Rainy Day PCL.  
  1434.  
  1435. (defvar *funcallable-instance-marker* (list "Funcallable Instance Marker"))
  1436.  
  1437. (defconstant funcallable-instance-closure-size 15)
  1438.  
  1439. (defun allocate-funcallable-instance-1 ()
  1440.   (let ((fin (allocate-funcallable-instance-2))
  1441.     (env
  1442.       (make-list funcallable-instance-closure-size :initial-element nil)))
  1443.     (set-cclosure-env fin env)
  1444.     #+:turbo-closure (si:turbo-closure fin)
  1445.     (dotimes (i (1- funcallable-instance-closure-size)) (pop env))
  1446.     (setf (car env) *funcallable-instance-marker*)
  1447.     fin))
  1448.  
  1449. (defun allocate-funcallable-instance-2 ()
  1450.   (let ((what-a-dumb-closure-variable ()))
  1451.     #'(lambda (&rest args)
  1452.     (declare (ignore args))
  1453.     (called-fin-without-function)
  1454.     (setq what-a-dumb-closure-variable
  1455.           (dummy-function what-a-dumb-closure-variable)))))
  1456.  
  1457. (defun funcallable-instance-p (x)
  1458.   (and (cclosurep x)
  1459.        (let ((env (cclosure-env x)))
  1460.      (when (listp env)
  1461.        (dotimes (i (1- funcallable-instance-closure-size)) (pop env))
  1462.        (eq (car env) *funcallable-instance-marker*)))))
  1463.  
  1464. (defun set-funcallable-instance-function (fin new-value)
  1465.   (cond ((not (funcallable-instance-p fin))
  1466.          (error "~S is not a funcallable-instance" fin))
  1467.         ((not (functionp new-value))
  1468.          (error "~S is not a function." new-value))
  1469.         ((cclosurep new-value)
  1470.          (let* ((fin-env (cclosure-env fin))
  1471.                 (new-env (cclosure-env new-value))
  1472.                 (new-env-size (length new-env))
  1473.                 (fin-env-size (- funcallable-instance-closure-size
  1474.                                  (length funcallable-instance-data)
  1475.                  1)))
  1476.            (cond ((<= new-env-size fin-env-size)
  1477.           (do ((i 0 (+ i 1))
  1478.                (new-env-tail new-env (cdr new-env-tail))
  1479.                (fin-env-tail fin-env (cdr fin-env-tail)))
  1480.               ((= i fin-env-size))
  1481.             (setf (car fin-env-tail)
  1482.               (if (< i new-env-size)
  1483.                   (car new-env-tail)
  1484.                   nil)))          
  1485.           (set-cclosure-self fin (cclosure-self new-value))
  1486.           (set-cclosure-data fin (cclosure-data new-value))
  1487.           (set-cclosure-start fin (cclosure-start new-value))
  1488.           (set-cclosure-size fin (cclosure-size new-value)))
  1489.                  (t                 
  1490.                   (set-funcallable-instance-function
  1491.                     fin
  1492.                     (make-trampoline new-value))))))
  1493.     ((typep new-value 'compiled-function)
  1494.      ;; Write NILs into the part of the cclosure environment that is
  1495.      ;; not being used to store the funcallable-instance-data.  Then
  1496.      ;; copy over the parts of the compiled function that need to be
  1497.      ;; copied over.
  1498.      (let ((env (cclosure-env fin)))
  1499.        (dotimes (i (- funcallable-instance-closure-size
  1500.               (length funcallable-instance-data)
  1501.               1))
  1502.          (setf (car env) nil)
  1503.          (pop env)))
  1504.      (set-cclosure-self fin (cfun-self new-value))
  1505.      (set-cclosure-data fin (cfun-data new-value))
  1506.      (set-cclosure-start fin (cfun-start new-value))
  1507.      (set-cclosure-size fin (cfun-size new-value)))     
  1508.         (t
  1509.          (set-funcallable-instance-function fin
  1510.                                             (make-trampoline new-value))))
  1511.   fin)
  1512.  
  1513.  
  1514. (defun make-trampoline (function)
  1515.   #'(lambda (&rest args)
  1516.       (apply function args)))
  1517.  
  1518. ;; this replaces funcallable-instance-data-1, set-funcallable-instance-data-1
  1519. ;; and the defsetf
  1520. (defmacro funcallable-instance-data-1 (fin data &environment env)
  1521.   ;; The compiler won't expand macros before deciding on optimizations,
  1522.   ;; so we must do it here.
  1523.   (let* ((pos-form (macroexpand `(funcallable-instance-data-position ,data)
  1524.                 env))
  1525.      (index-form (if (constantp pos-form)
  1526.              (- funcallable-instance-closure-size
  1527.                 (eval pos-form)
  1528.                 2)
  1529.              `(- funcallable-instance-closure-size
  1530.                  (funcallable-instance-data-position ,data)
  1531.                  2))))
  1532.     #+:turbo-closure `(car (tc-cclosure-env-nthcdr ,index-form ,fin))
  1533.     #-:turbo-closure `(nth ,index-form (cclosure-env ,fin))))
  1534.  
  1535. )
  1536.  
  1537.  
  1538. ;;;
  1539. ;;; In H.P. Common Lisp
  1540. ;;; This code was originally written by:
  1541. ;;;    kempf@hplabs.hp.com     (James Kempf)
  1542. ;;;    dsouza@hplabs.hp.com    (Roy D'Souza)
  1543. ;;;
  1544. #+HP-HPLabs
  1545. (progn
  1546.  
  1547. (defmacro fin-closure-size ()`(prim::@* 6 prim::bytes-per-word))
  1548.  
  1549. (defmacro fin-set-mem-hword ()
  1550.   `(prim::@set-mem-hword
  1551.      (prim::@+ fin (prim::@<< 2 1))
  1552.      (prim::@+ (prim::@<< 2 8)
  1553.            (prim::@fundef-info-parms (prim::@fundef-info fundef)))))
  1554.  
  1555. (defun allocate-funcallable-instance-1()
  1556.   (let* ((fundef
  1557.        #'(lambda (&rest ignore)
  1558.            (declare (ignore ignore))
  1559.            (called-fin-without-function)))
  1560.      (static-link (vector 'lisp::*undefined* NIL NIL NIL NIL NIL))
  1561.      (fin (prim::@make-fundef (fin-closure-size))))
  1562.     (fin-set-mem-hword)
  1563.     (prim::@set-svref fin 2 fundef)
  1564.     (prim::@set-svref fin 3 static-link)
  1565.     (prim::@set-svref fin 4 0) 
  1566.     (impl::PlantclosureHook fin)
  1567.     fin))
  1568.  
  1569. (defmacro funcallable-instance-p (possible-fin)
  1570.   `(= (fin-closure-size) (prim::@header-inf ,possible-fin)))
  1571.  
  1572. (defun set-funcallable-instance-function (fin new-function)
  1573.   (cond ((not (funcallable-instance-p fin))
  1574.      (error "~S is not a funcallable instance.~%" fin))
  1575.     ((not (functionp new-function))
  1576.      (error "~S is not a function." new-function))
  1577.     (T
  1578.      (prim::@set-svref fin 2 new-function))))
  1579.  
  1580. (defmacro funcallable-instance-data-1 (fin data)
  1581.   `(prim::@svref (prim::@closure-static-link ,fin)
  1582.          (+ 2 (funcallable-instance-data-position ,data))))
  1583.  
  1584. (defsetf funcallable-instance-data-1 (fin data) (new-value)
  1585.   `(prim::@set-svref (prim::@closure-static-link ,fin)
  1586.              (+ (funcallable-instance-data-position ,data) 2)
  1587.              ,new-value))
  1588.  
  1589. (defun funcallable-instance-name (fin)
  1590.   (prim::@svref (prim::@closure-static-link fin) 1))
  1591.  
  1592. (defsetf funcallable-instance-name set-funcallable-instance-name)
  1593.  
  1594. (defun set-funcallable-instance-name (fin new-name)
  1595.   (prim::@set-svref (prim::@closure-static-link fin) 1 new-name))
  1596.  
  1597. );end #+HP
  1598.  
  1599.  
  1600.  
  1601. ;;;
  1602. ;;; In Golden Common Lisp.
  1603. ;;; This code was originally written by:
  1604. ;;;    dan%acorn@Live-Oak.LCS.MIT.edu     (Dan Jacobs)
  1605. ;;;
  1606. ;;; GCLISP supports named structures that are specially marked as funcallable.
  1607. ;;; This allows FUNCALLABLE-INSTANCE-P to be a normal structure predicate,
  1608. ;;; and allows ALLOCATE-FUNCALLABLE-INSTANCE-1 to be a normal boa-constructor.
  1609. ;;; 
  1610. #+GCLISP
  1611. (progn
  1612.  
  1613. (defstruct (%funcallable-instance
  1614.          (:predicate funcallable-instance-p)
  1615.          (:copier nil)
  1616.          (:constructor allocate-funcallable-instance-1 ())
  1617.          (:print-function
  1618.           (lambda (struct stream depth)
  1619.         (declare (ignore depth))
  1620.         (print-object struct stream))))
  1621.   (function    #'(lambda (ignore-this &rest ignore-these-too)
  1622.             (declare (ignore ignore-this ignore-these-too))
  1623.             (called-fin-without-function))
  1624.         :type function)
  1625.   (%hidden%    'gclisp::funcallable :read-only t)
  1626.   (data        (vector nil nil) :type simple-vector :read-only t))
  1627.  
  1628. (proclaim '(inline set-funcallable-instance-function))
  1629. (defun set-funcallable-instance-function (fin new-value)
  1630.   (setf (%funcallable-instance-function fin) new-value))
  1631.  
  1632. (defmacro funcallable-instance-data-1 (fin data)
  1633.   `(svref (%funcallable-instance-data ,fin)
  1634.       (funcallable-instance-data-position ,data)))
  1635.  
  1636. )
  1637.  
  1638.  
  1639. ;;;
  1640. ;;; Explorer Common Lisp
  1641. ;;; This code was originally written by:
  1642. ;;;    Dussud%Jenner@csl.ti.com
  1643. ;;;    
  1644. #+ti
  1645. (progn
  1646.  
  1647. #+(or :ti-release-3 (and :ti-release-2 elroy))
  1648. (defmacro lexical-closure-environment (l)
  1649.   `(cdr (si:%make-pointer si:dtp-list
  1650.               (cdr (si:%make-pointer si:dtp-list ,l)))))
  1651.  
  1652. #-(or :ti-release-3 elroy)
  1653. (defmacro lexical-closure-environment (l)
  1654.   `(caar (si:%make-pointer si:dtp-list
  1655.                (cdr (si:%make-pointer si:dtp-list ,l)))))
  1656.  
  1657. (defmacro lexical-closure-function (l)
  1658.   `(car (si:%make-pointer si:dtp-list ,l)))
  1659.  
  1660.  
  1661. (defvar *funcallable-instance-marker* (list "Funcallable Instance Marker"))
  1662.  
  1663. (defconstant funcallable-instance-closure-size 15) ; NOTE: In order to avoid
  1664.                            ; hassles with the reader,
  1665. (defmacro allocate-funcallable-instance-2 ()       ; these two 15's are the
  1666.   (let ((l ()))                       ; same.  Be sure to keep
  1667.     (dotimes (i 15)                   ; them consistent.
  1668.       (push (list (gensym) nil) l))
  1669.     `(let ,l
  1670.        #'(lambda (ignore &rest ignore-them-too)
  1671.        (declare (ignore ignore ignore-them-too))
  1672.        (called-fin-without-function)
  1673.        (values . ,(mapcar #'car l))))))
  1674.  
  1675. (defun allocate-funcallable-instance-1 ()
  1676.   (let* ((new-fin (allocate-funcallable-instance-2)))
  1677.     (setf (car (nthcdr (1- funcallable-instance-closure-size)
  1678.                (lexical-closure-environment new-fin)))
  1679.       *funcallable-instance-marker*) 
  1680.     new-fin))
  1681.  
  1682. (eval-when (eval) (compile 'allocate-funcallable-instance-1))
  1683.  
  1684. (proclaim '(inline funcallable-instance-p))
  1685. (defun funcallable-instance-p (x)
  1686.   (and (typep x #+:ti-release-2 'closure
  1687.             #+:ti-release-3 'si:lexical-closure)
  1688.        (let ((env (lexical-closure-environment x)))
  1689.      (eq (nth (1- funcallable-instance-closure-size) env)
  1690.          *funcallable-instance-marker*))))
  1691.  
  1692. (defun set-funcallable-instance-function (fin new-value)
  1693.   (cond ((not (funcallable-instance-p fin))
  1694.      (error "~S is not a funcallable-instance"))
  1695.     ((not (functionp new-value))
  1696.      (error "~S is not a function."))
  1697.     ((typep new-value 'si:lexical-closure)
  1698.      (let* ((fin-env (lexical-closure-environment fin))
  1699.         (new-env (lexical-closure-environment new-value))
  1700.         (new-env-size (length new-env))
  1701.         (fin-env-size (- funcallable-instance-closure-size
  1702.                  (length funcallable-instance-data)
  1703.                  1)))
  1704.        (cond ((<= new-env-size fin-env-size)
  1705.           (do ((i 0 (+ i 1))
  1706.                (new-env-tail new-env (cdr new-env-tail))
  1707.                (fin-env-tail fin-env (cdr fin-env-tail)))
  1708.               ((= i fin-env-size))
  1709.             (setf (car fin-env-tail)
  1710.               (if (< i new-env-size)
  1711.                   (car new-env-tail)
  1712.                   nil)))          
  1713.           (setf (lexical-closure-function fin)
  1714.             (lexical-closure-function new-value)))
  1715.          (t
  1716.           (set-funcallable-instance-function
  1717.             fin
  1718.             (make-trampoline new-value))))))
  1719.     (t
  1720.      (set-funcallable-instance-function fin
  1721.                         (make-trampoline new-value)))))
  1722.  
  1723. (defun make-trampoline (function)
  1724.   (let ((tmp))
  1725.     #'(lambda (&rest args) tmp
  1726.     (apply function args))))
  1727.  
  1728. (eval-when (eval) (compile 'make-trampoline))
  1729.     
  1730. (defmacro funcallable-instance-data-1 (fin data)
  1731.   `(let ((env (lexical-closure-environment ,fin)))
  1732.      (nth (- funcallable-instance-closure-size
  1733.          (funcallable-instance-data-position ,data)
  1734.          2)
  1735.       env)))
  1736.  
  1737.  
  1738. (defsetf funcallable-instance-data-1 (fin data) (new-value)
  1739.   `(let ((env (lexical-closure-environment ,fin)))
  1740.      (setf (car (nthcdr (- funcallable-instance-closure-size
  1741.                (funcallable-instance-data-position ,data)
  1742.                2)
  1743.             env))
  1744.        ,new-value)))
  1745.  
  1746. );end of code for TI
  1747.  
  1748.  
  1749. ;;; Implemented by Bein@pyramid -- Tue Aug 25 19:05:17 1987
  1750. ;;;
  1751. ;;; A FIN is a distinct type of object which FUNCALL,EVAL, and APPLY
  1752. ;;; recognize as functions. Both Compiled-Function-P and functionp
  1753. ;;; recognize FINs as first class functions.
  1754. ;;;
  1755. ;;; This does not work with PyrLisp versions earlier than 1.1..
  1756.  
  1757. #+pyramid
  1758. (progn
  1759.  
  1760. (defun make-trampoline (function)
  1761.     #'(lambda (&rest args) (apply function args)))
  1762.  
  1763. (defun un-initialized-fin (&rest trash)
  1764.     (declare (ignore trash))
  1765.     (called-fin-without-function))
  1766.  
  1767. (eval-when (eval)
  1768.     (compile 'make-trampoline)
  1769.     (compile 'un-initialized-fin))
  1770.  
  1771. (defun allocate-funcallable-instance-1 ()
  1772.     (let ((fin (system::alloc-funcallable-instance)))
  1773.       (system::set-fin-function fin #'un-initialized-fin)
  1774.       fin))
  1775.          
  1776. (defun funcallable-instance-p (object)
  1777.   (typep object 'lisp::funcallable-instance))
  1778.  
  1779. (clc::deftransform funcallable-instance-p trans-fin-p (object)
  1780.     `(typep ,object 'lisp::funcallable-instance))
  1781.  
  1782. (defun set-funcallable-instance-function (fin new-value)
  1783.     (or (funcallable-instance-p fin)
  1784.     (error "~S is not a funcallable-instance." fin))
  1785.     (cond ((not (functionp new-value))
  1786.        (error "~S is not a function." new-value))
  1787.       ((not (lisp::compiled-function-p new-value))
  1788.        (set-funcallable-instance-function fin
  1789.                           (make-trampoline new-value)))
  1790.       (t
  1791.        (system::set-fin-function fin new-value))))
  1792.  
  1793. (defun funcallable-instance-data-1 (fin data-name)
  1794.   (system::get-fin-data fin
  1795.             (funcallable-instance-data-position data-name)))
  1796.  
  1797. (defun set-funcallable-instance-data-1 (fin data-name value)
  1798.   (system::set-fin-data fin
  1799.             (funcallable-instance-data-position data-name)
  1800.             value))
  1801.  
  1802. (defsetf funcallable-instance-data-1 set-funcallable-instance-data-1)
  1803.  
  1804. ); End of #+pyramid
  1805.  
  1806.  
  1807. ;;;
  1808. ;;; For Coral Lisp
  1809. ;;;
  1810. #+:coral
  1811. (progn
  1812.   
  1813. (defconstant ccl::$v_istruct 22)
  1814. (defvar ccl::initial-fin-slots (make-list (length funcallable-instance-data)))
  1815. (defconstant ccl::fin-function 1)
  1816. (defconstant ccl::fin-data (+ ccl::FIN-function 1))
  1817.  
  1818. (defun allocate-funcallable-instance-1 ()
  1819.   (apply #'ccl::%gvector 
  1820.          ccl::$v_istruct
  1821.          'ccl::funcallable-instance
  1822.          #'(lambda (&rest ignore)
  1823.              (declare (ignore ignore))
  1824.          (called-fin-without-function))
  1825.          ccl::initial-fin-slots))
  1826.  
  1827. #+:ccl-1.3
  1828. (eval-when (eval compile load)
  1829.  
  1830. ;;; Make uvector-based objects (like funcallable instances) print better.
  1831. (defun print-uvector-object (obj stream &optional print-level)
  1832.   (declare (ignore print-level))
  1833.   (print-object obj stream))
  1834.  
  1835. ;;; Inform the print system about funcallable instance uvectors.
  1836. (pushnew (cons 'ccl::funcallable-instance #'print-uvector-object)
  1837.      ccl:*write-uvector-alist*
  1838.      :test #'equal)
  1839.  
  1840. )
  1841.  
  1842. (defun funcallable-instance-p (x)
  1843.   (and (eq (ccl::%type-of x) 'ccl::internal-structure)
  1844.        (eq (ccl::%uvref x 0) 'ccl::funcallable-instance)))
  1845.  
  1846. (defun set-funcallable-instance-function (fin new-value)
  1847.   (unless (funcallable-instance-p fin)
  1848.     (error "~S is not a funcallable-instance." fin))
  1849.   (unless (functionp new-value)
  1850.     (error "~S is not a function." new-value))
  1851.   (ccl::%uvset fin ccl::FIN-function new-value))
  1852.  
  1853. (defmacro funcallable-instance-data-1 (fin data-name)
  1854.   `(ccl::%uvref ,fin 
  1855.                 (+ (funcallable-instance-data-position ,data-name)
  1856.            ccl::FIN-data)))
  1857.  
  1858. (defsetf funcallable-instance-data-1 (fin data) (new-value)
  1859.   `(ccl::%uvset ,fin 
  1860.                 (+ (funcallable-instance-data-position ,data) ccl::FIN-data)
  1861.                 ,new-value))
  1862.  
  1863. ); End of #+:coral
  1864.  
  1865.  
  1866.   
  1867. ;;;; Slightly Higher-Level stuff built on the implementation-dependent stuff.
  1868. ;;;
  1869. ;;;
  1870.  
  1871. (defmacro fsc-instance-p (fin)
  1872.   `(funcallable-instance-p ,fin))
  1873.  
  1874. (defmacro fsc-instance-class (fin)
  1875.   `(wrapper-class (funcallable-instance-data-1 ,fin 'wrapper)))
  1876.  
  1877. (defmacro fsc-instance-wrapper (fin)
  1878.   `(funcallable-instance-data-1 ,fin 'wrapper))
  1879.  
  1880. (defmacro fsc-instance-slots (fin)
  1881.   `(funcallable-instance-data-1 ,fin 'slots))
  1882.  
  1883. (defun allocate-funcallable-instance (wrapper number-of-static-slots)
  1884.   (let ((fin (allocate-funcallable-instance-1))
  1885.         (slots
  1886.           (%allocate-static-slot-storage--class number-of-static-slots)))
  1887.     (setf (fsc-instance-wrapper fin) wrapper
  1888.           (fsc-instance-slots fin) slots)
  1889.     fin))
  1890.